package cn.jofei.server.http.filter;

import cn.jofei.common.RedirectInfo;
import cn.jofei.common.ano.Component;
import cn.jofei.common.ano.Order;
import cn.jofei.common.config.AppProperties;
import cn.jofei.common.enums.Headers;
import cn.jofei.common.util.Utils;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;

import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * RedirectFilter
 *
 * @author Jofei Bao
 * @version ngbao v1.0.2
 * @date 2022年07月08日 23:06
 */
@Order(index = -200)
@Component
public class RedirectFilter implements HttpRequestFilter {

    private static final Map<String, RedirectInfo> REDIRECT_INFOS = new HashMap<>();

    private static final int HTTPS_PORT = AppProperties.get("server.listen.https.port", Integer.class).orElse(443);

    static {
        List<String> lists = AppProperties.get("server.redirect", List.class).orElse(new ArrayList());
        if (lists != null && lists.size() > 0) {
            for (String list : lists) {
                list = AppProperties.replaceVar(list);
                String[] s = list.split(" ");
                if (Utils.nonNull(s[0])) {
                    for (String host : s[0].split(";")) {
                        RedirectInfo redirectInfo = new RedirectInfo();
                        redirectInfo.setSubdomains(host);
                        redirectInfo.setUrlTo(s[1]);
                        REDIRECT_INFOS.put(host, redirectInfo);
                    }
                }
            }
        }
    }

    @Override
    public boolean doFilter(HttpRequest request, ChannelHandlerContext ctx) throws Exception {
        int port = ((InetSocketAddress) ctx.channel().localAddress()).getPort();
        if (HTTPS_PORT != port) {
            String host = getHost(request);
            if (Utils.nonNull(host)) {
                RedirectInfo redirectInfo = REDIRECT_INFOS.get(host);
                if (Utils.nonNull(redirectInfo)) {
                    DefaultFullHttpResponse response = new DefaultFullHttpResponse(request.protocolVersion(), HttpResponseStatus.FOUND);
                    response.headers().add(Headers.Location, redirectInfo.getUrlTo() + request.uri());
                    ctx.writeAndFlush(response);
                    ctx.close();
                    return true;
                }
            }
        }
        return false;
    }
}
